﻿using OPCPlatformCore.Exceptions;
using OPCPlatformCore.Implementations;
using OPCPlatformCore.Models.OPCServerModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OPCPlateform
{
    public partial class frmMain : Form
    {
        OPCServerMachine testMachine;
        OPCServerMachine randomMachine;
        OPCServerMachine testMachine1;
        OPCServerMachine randomMachine1;
        string connectionString;
        System.Threading.Timer asyncReadTest;
        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            connectionString = ConfigurationManager.ConnectionStrings["OPCServer"].ConnectionString;

            //machine1
            testMachine = new OPCServerMachine("SimulatorMachine");
            testMachine.AddTag("Test1", "Simulator.TestMachine.RandomValue1");
            testMachine.AddTag("Test2", "Simulator.TestMachine.RandomValue2");
            testMachine.AddTag("Test3", "Simulator.TestMachine.RandomValue3");
            testMachine.AddTag("Test4", "Simulator.TestMachine.RandomValue4");
            testMachine.AddTag("Test5", "Simulator.TestMachine.RandomValue5");

            randomMachine = new OPCServerMachine("RandomMachine");
            randomMachine.AddTag("Value1", "Simulator.RandomMachine.RandomValue1");
            randomMachine.AddTag("Value2", "Simulator.RandomMachine.RandomValue2");

            testMachine1 = new OPCServerMachine("TestMachine1");
            testMachine1.AddTag("Value1", "SimulatorMachine.TestMachine.RandomValue1");
            testMachine1.AddTag("Value2", "SimulatorMachine.TestMachine.RandomValue2");

            randomMachine1 = new OPCServerMachine("RandomMachine1");
            randomMachine1.AddTag("Value1", "SimulatorMachine.RandomMachine.RandomValue1");
            randomMachine1.AddTag("Value2", "SimulatorMachine.RandomMachine.RandomValue2");

            testMachine.TagInfos.ForEach(t => t.NeedRead = true);
            randomMachine.TagInfos.ForEach(t => t.NeedRead = true);
            testMachine1.TagInfos.ForEach(t => t.NeedRead = true);
            randomMachine1.TagInfos.ForEach(t => t.NeedRead = true);

            asyncReadTest = new System.Threading.Timer(ThreadPoolMethod, null, Timeout.Infinite, Timeout.Infinite);
        }
        private void ThreadPoolMethod(object sender)
        {
            asyncReadTest.Change(Timeout.Infinite, Timeout.Infinite);
            Task t1 = Task.Run(() => RefreshDataTest(null));
            Task t2 = Task.Run(() => RefreshDataTest1(null));
            Task t3 = Task.Run(() => RefreshDataRandom(null));
            Task t4 = Task.Run(() => RefreshDataRandom1(null));
            Task.WaitAny(t1, t2, t3, t4);
            //强制回收垃圾
            GC.Collect();
            asyncReadTest.Change(300, Timeout.Infinite);
        }
        #region 读取数据测试
        private void RefreshDataTest(object sender)
        {
            try
            {
                //以下对象每个线程创建一次,避免多线程造成的效率损失
                OPCServerDataProvider odp = new OPCServerDataProvider(connectionString);
                odp.RegisterMachine(testMachine);
                testMachine = odp.GetData(testMachine);
                StringBuilder sb = new StringBuilder();
                foreach (var item in testMachine.TagInfos)
                {
                    sb.Append(item.FriendlyName);
                    sb.Append(":");
                    sb.Append(item.Value);
                    sb.Append("     ");
                    sb.Append(item.LastUpdateTime.ToString("yyyy/MM/dd HH:mm:ss:fff"));
                    sb.Append("\r\n");
                }

                if (txtReadData1.InvokeRequired)
                {
                    txtReadData1.Invoke(new Action(() =>
                    {
                        txtReadData1.Text = sb.ToString();
                    }));
                }
            }
            catch(OPCServerReadException e)
            {
                if (lblMessage.InvokeRequired)
                {
                    lblMessage.Invoke(new Action(() =>
                    {
                        lblMessage.Text = e.Message;
                    }));
                }
                Thread.Sleep(3000);//读取异常后,暂停3s
            }
            catch
            {
                throw;
            }
            finally
            {
            }
        }
        private void RefreshDataRandom(object sender)
        {
            try
            {
                //以下对象每个线程创建一次,避免多线程造成的效率损失
                OPCServerDataProvider odp = new OPCServerDataProvider(connectionString);
                odp.RegisterMachine(randomMachine);
                randomMachine = odp.GetData(randomMachine);
                StringBuilder sb = new StringBuilder();
                foreach (var item in randomMachine.TagInfos)
                {
                    sb.Append(item.FriendlyName);
                    sb.Append(":");
                    sb.Append(item.Value);
                    sb.Append("     ");
                    sb.Append(item.LastUpdateTime.ToString("yyyy/MM/dd HH:mm:ss:fff"));
                    sb.Append("\r\n");
                }

                if (txtReadData2.InvokeRequired)
                {
                    txtReadData2.Invoke(new Action(() =>
                    {
                        txtReadData2.Text = sb.ToString();
                    }));
                }
            }
            catch (OPCServerReadException e)
            {
                if (lblMessage.InvokeRequired)
                {
                    lblMessage.Invoke(new Action(() =>
                    {
                        lblMessage.Text = e.Message;
                    }));
                }
                Thread.Sleep(3000);//读取异常后,暂停3s
            }
            catch
            {
                throw;
            }
            finally
            {
            }
        }

        private void RefreshDataTest1(object sender)
        {
            try
            {
                //以下对象每个线程创建一次,避免多线程造成的效率损失
                OPCServerDataProvider odp = new OPCServerDataProvider(connectionString);
                odp.RegisterMachine(testMachine1);
                testMachine1 = odp.GetData(testMachine1);
                StringBuilder sb = new StringBuilder();
                foreach (var item in testMachine1.TagInfos)
                {
                    sb.Append(item.FriendlyName);
                    sb.Append(":");
                    sb.Append(item.Value);
                    sb.Append("     ");
                    sb.Append(item.LastUpdateTime.ToString("yyyy/MM/dd HH:mm:ss:fff"));
                    sb.Append("\r\n");
                }

                if (txtReadData3.InvokeRequired)
                {
                    txtReadData3.Invoke(new Action(() =>
                    {
                        txtReadData3.Text = sb.ToString();
                    }));
                }
            }
            catch (OPCServerReadException e)
            {
                if (lblMessage.InvokeRequired)
                {
                    lblMessage.Invoke(new Action(() =>
                    {
                        lblMessage.Text = e.Message;
                    }));
                }
                Thread.Sleep(3000);//读取异常后,暂停3s
            }
            catch
            {
                throw;
            }
            finally
            {
            }
        }
        private void RefreshDataRandom1(object sender)
        {
            try
            {
                //以下对象每个线程创建一次,避免多线程造成的效率损失
                OPCServerDataProvider odp = new OPCServerDataProvider(connectionString);
                odp.RegisterMachine(randomMachine1);
                randomMachine1 = odp.GetData(randomMachine1);
                StringBuilder sb = new StringBuilder();
                foreach (var item in randomMachine1.TagInfos)
                {
                    sb.Append(item.FriendlyName);
                    sb.Append(":");
                    sb.Append(item.Value);
                    sb.Append("     ");
                    sb.Append(item.LastUpdateTime.ToString("yyyy/MM/dd HH:mm:ss:fff"));
                    sb.Append("\r\n");
                }

                if (txtReadData4.InvokeRequired)
                {
                    txtReadData4.Invoke(new Action(() =>
                    {
                        txtReadData4.Text = sb.ToString();
                    }));
                }
            }
            catch (OPCServerReadException e)
            {
                if (lblMessage.InvokeRequired)
                {
                    lblMessage.Invoke(new Action(() =>
                    {
                        lblMessage.Text = e.Message;
                    }));
                }
                Thread.Sleep(3000);//读取异常后,暂停3s
            }
            catch
            {
                throw;
            }
            finally
            {
                
            }
        }
        #endregion

        private void btnReadData_Click(object sender, EventArgs e)
        {
            asyncReadTest.Change(0, Timeout.Infinite);
            lblMessage.Text = "开始读取数据!";
        }

        private void btnWriteData_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtWriteData.Text))
            {
                MessageBox.Show("设置数据格式错误,请重新编辑!");
                return;
            }
            string[] values = txtWriteData.Text.Split(',');
            testMachine.TagInfos[2].NeedWrite = true;
            testMachine.TagInfos[3].NeedWrite = true;
            testMachine.TagInfos[4].NeedWrite = true;
            for (int i = 0; i < testMachine.TagInfos.Count; i++)
            {
                testMachine.TagInfos[i].SetValue(values[i]);
            }
            //以下代码必须放在同一个线程中,否则会造成程序运行完成但是卡死的问题,或者数据没有写成功
            Thread t = new Thread(new ThreadStart(() =>
            {
                OPCServerDataProvider odp = new OPCServerDataProvider(connectionString);
                odp.RegisterMachine(testMachine);
                var r = odp.WriteData(testMachine);
                if (r)
                {
                    if (lblMessage.InvokeRequired)
                    {
                        lblMessage.Invoke(new Action(() =>
                        {
                            lblMessage.Text = "设置成功!";
                        }));
                    }
                }
            }));
            t.Start();
        }
    }
}
